# encoding: utf-8
# @author: 搬砖柯
# @file: element_update.py
# @time: 2025/5/30 11:35
# @desc:


import os
import pandas as pd
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
import shutil
from common.get_logger import GetLogger
from common.path_setting import ensure_path_sep

log = GetLogger.get_logger()

config = {
    "directory": ensure_path_sep('/data/update_test'),  # 包含Excel文件的目录路径
    "old_locator_type": "css selector",  # 旧的定位方式
    "old_locator_value": "input[placeholder='密码']",  # 旧的定位元素值
    "new_locator_type": "xpath",  # 新的定位方式
    "new_locator_value": "//input[@id='password']",  # 新的定位元素值
    "locator_type_col": "定位方式",  # 定位方式列名
    "element_col": "定位元素位置",  # 定位元素位置列名
    "output_mode": "overwrite",  # 输出模式: "overwrite" 覆盖原文件, "copy" 生成副本
    "execute": False  # 是否执行实际修改(True为执行，False为预览)
}


def find_excel_files(directory):
    """查找目录下所有Excel文件"""
    excel_files = []
    for root, _, files in os.walk(directory):
        for file in files:
            if file.endswith(('.xlsx', '.xls')):
                excel_files.append(os.path.join(root, file))
    return excel_files


def update_excel_element(file_path, old_locator, new_locator,
                         locator_type_col="定位方式", element_col="定位元素位置",
                         output_mode="overwrite", dry_run=True):
    """更新Excel文件中的元素定位信息

    output_mode: "overwrite" 覆盖原文件, "copy" 生成副本
    """
    try:
        # 确定输出文件路径
        if output_mode == "copy":
            file_dir, file_name = os.path.split(file_path)
            base_name, ext = os.path.splitext(file_name)
            output_file = os.path.join(file_dir, f"{base_name}_updated{ext}")

            # 如果是预览模式，不实际复制文件
            if not dry_run:
                # 先复制原文件
                shutil.copy2(file_path, output_file)
                log.info(f"已生成副本: {output_file}")
        else:
            output_file = file_path

        # 读取Excel文件
        xls = pd.ExcelFile(output_file if output_mode == "copy" and not dry_run else file_path)
        sheet_names = xls.sheet_names

        # 打开工作簿用于精确修改
        wb = load_workbook(output_file if output_mode == "copy" and not dry_run else file_path)

        # 记录修改统计
        stats = {"total_files": 1, "modified_sheets": 0, "modified_cells": 0}
        modified_sheets = []

        for sheet_name in sheet_names:
            # 使用pandas读取数据
            df = xls.parse(sheet_name)

            # 检查列是否存在
            if locator_type_col not in df.columns or element_col not in df.columns:
                log.debug(f"工作表 '{sheet_name}' 中找不到指定的列")
                continue

            # 查找匹配的行
            mask = (df[locator_type_col] == old_locator[0]) & (df[element_col] == old_locator[1])
            rows_to_update = df[mask]

            if not rows_to_update.empty:
                # 获取工作表
                ws = wb[sheet_name]

                # 获取列索引
                locator_type_idx = df.columns.get_loc(locator_type_col) + 1  # Excel列索引从1开始
                element_idx = df.columns.get_loc(element_col) + 1

                # 获取列字母
                locator_type_letter = get_column_letter(locator_type_idx)
                element_letter = get_column_letter(element_idx)

                # 更新每一行
                for idx in rows_to_update.index:
                    excel_row = idx + 2  # Excel行索引从1开始，标题行占一行

                    if not dry_run:
                        # 修改定位方式
                        ws[f"{locator_type_letter}{excel_row}"] = new_locator[0]
                        # 修改元素位置
                        ws[f"{element_letter}{excel_row}"] = new_locator[1]

                    stats["modified_cells"] += 1

                stats["modified_sheets"] += 1
                modified_sheets.append(sheet_name)
                log.info(f"文件: {file_path}, 工作表: '{sheet_name}', 修改行数: {len(rows_to_update)}")

        # 保存修改
        if stats["modified_sheets"] > 0 and not dry_run:
            wb.save(output_file)
            log.info(f"已{'覆盖' if output_mode == 'overwrite' else '保存到副本'}文件: {output_file}")

        return stats, modified_sheets

    except Exception as e:
        log.error(f"处理文件 {file_path} 时出错: {str(e)}")
        return {"total_files": 1, "modified_sheets": 0, "modified_cells": 0}, []


def main():
    # 配置参数 - 在这里修改你需要的参数值
    # 输入的旧定位信息
    old_locator = (config["old_locator_type"], config["old_locator_value"])
    # 新定位信息
    new_locator = (config["new_locator_type"], config["new_locator_value"])

    log.info(f"开始查找并更新元素定位信息...")
    log.info(f"查找目录: {config['directory']}")
    log.info(f"旧定位信息: 方式='{old_locator[0]}', 值='{old_locator[1]}'")
    log.info(f"新定位信息: 方式='{new_locator[0]}', 值='{new_locator[1]}'")
    log.info(f"定位方式列名: '{config['locator_type_col']}', 定位元素位置列名: '{config['element_col']}'")
    log.info(f"输出模式: {'覆盖原文件' if config['output_mode'] == 'overwrite' else '生成副本'}")
    log.info(f"执行模式: {'预览' if not config['execute'] else '实际修改'}")

    # 查找所有Excel文件
    excel_files = find_excel_files(config["directory"])
    total_files = len(excel_files)
    log.info(f"找到 {total_files} 个Excel文件")

    # 统计信息
    overall_stats = {"total_files": 0, "modified_files": 0, "modified_sheets": 0, "modified_cells": 0}

    # 处理每个文件
    for i, file_path in enumerate(excel_files, 1):
        log.info(f"正在处理文件 ({i}/{total_files}): {file_path}")
        stats, modified_sheets = update_excel_element(
            file_path, old_locator, new_locator,
            config["locator_type_col"], config["element_col"],
            config["output_mode"],
            dry_run=not config["execute"]
        )

        overall_stats["total_files"] += stats["total_files"]
        if stats["modified_sheets"] > 0:
            overall_stats["modified_files"] += 1
        overall_stats["modified_sheets"] += stats["modified_sheets"]
        overall_stats["modified_cells"] += stats["modified_cells"]

    # 输出统计结果
    log.info("=" * 50)
    log.info("处理结果统计:")
    log.info(f"总处理文件数: {overall_stats['total_files']}")
    log.info(f"修改的文件数: {overall_stats['modified_files']}")
    log.info(f"修改的工作表数: {overall_stats['modified_sheets']}")
    log.info(f"修改的单元格数: {overall_stats['modified_cells']}")
    log.info("=" * 50)

    if not config["execute"]:
        log.info("注意: 这只是预览模式，未实际修改任何文件。若要执行实际修改，请将config['execute']设置为True。")


if __name__ == "__main__":
    main()



